package com.chao.yyks.modular.sys.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chao.common.bean.IUser;
import com.chao.common.util.*;
import com.chao.common.util.exception.SysException;
import com.chao.common.util.redis.SysRedis;
import com.chao.yyks.modular.ranking.bean.EnRanking;
import com.chao.yyks.modular.ranking.mapper.EnRankingMapper;
import com.chao.yyks.modular.sys.bean.EnClasss;
import com.chao.yyks.modular.sys.bean.EnStudent;
import com.chao.yyks.modular.sys.bean.LoginUser;
import com.chao.yyks.modular.sys.mapper.EnClasssMapper;
import com.chao.yyks.modular.sys.mapper.EnClasssTypeMapper;
import com.chao.yyks.modular.sys.mapper.EnStudentMapper;
import com.chao.yyks.modular.sys.service.EnStudentService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.chao.common.util.reaction.PageList;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.chao.common.util.SysConstant.TOKEN;


/**
 * 学生ServiceImpl
 * chao
 * 2024-09-09
 */
@Service
public class EnStudentServiceImpl implements EnStudentService {

	/**
	 * 学生Mapper
	 */
	@Autowired
	private EnStudentMapper enStudentMapper;

	/**
	 * 班级Mapper
	 */
	@Autowired
	private EnClasssMapper enClasssMapper;

	/**
	 * 问题数量配置Mapper
	 */
	@Autowired
	private EnClasssTypeMapper enClasssTypeMapper;

	/**
	 * 学生排名Mapper
	 */
	@Autowired
	private EnRankingMapper enRankingMapper;


	@Autowired
	@Qualifier("wxMaService")
	private WxMaService wxService;

	/**
	 * 新增学生
	 */
	@Override
	@Transactional
	public void insertEnStudent(EnStudent enStudent){
		String studentKey = enStudent.getStudentKey();
		if(StrUtile.isEmpty(studentKey)){
			throw new SysException("请输入学号!");
		}
		enStudent.setStudentPassword(StrUtile.getMD5(studentKey.substring(studentKey.length() - 6)));
		enStudent.setStudentId(StrUtile.getId());
		enStudent.setCtime(new Date());
		enStudent.setCreateUserId(RequestUtile.getLoginUserId());
		enStudentMapper.insertEnStudent(enStudent);
	}

	/**
	 * 修改学生
	 */
	@Override
	@Transactional
	public void updateEnStudent(EnStudent enStudent){
		if(StrUtile.isEmpty(enStudent.getStudentKey())){
			throw new SysException("请输入学号!");
		}
		EnStudent enStudentPojo = enStudentMapper.selectEnStudentByStudentId(enStudent.getStudentId());
		if(null == enStudentPojo){
			throw new SysException("修改学生失败:记录不存在!");
		}
		enStudentMapper.updateEnStudent(enStudent);
	}

	/**
	 * 删除学生
	 */
	@Override
	@Transactional
	public void deleteEnStudent(String studentId){
		EnStudent enStudent = enStudentMapper.selectEnStudentByStudentId(studentId);
		if(null == enStudent){
			throw new SysException("删除学生失败:记录不存在!");
		}
		enStudentMapper.deleteEnStudent(studentId);
	}

	/**
	 * 修改用户密码
	 */
	@Override
	public void updatePassword(JSONObject json){
		String oldPassword = json.getString("oldPassword");
		EnStudent enStudent = enStudentMapper.selectEnStudentByStudentId(RequestUtile.getLoginUserId());
		//校验密码是否正确
		if(!enStudent.getStudentPassword().equals(StrUtile.getMD5(oldPassword))){
			throw new SysException("请输入正确的当前密码后再进行修改！");
		}
		String newPassword = json.getString("newPassword");
		enStudentMapper.updatePassword(RequestUtile.getLoginUserId(),StrUtile.getMD5(newPassword));
	}

	/**
	 * 重置用户密码
	 */
	@Override
	public void resetPassword(String studentId){
		EnStudent enStudent = enStudentMapper.selectEnStudentByStudentId(studentId);
		if(null == enStudent){
			throw new SysException("重置用户密码失败:学生不存在!");
		}
		enStudentMapper.updatePassword(studentId,StrUtile.getMD5(enStudent.getStudentKey().substring(enStudent.getStudentKey().length()-6)));
	}

	/**
	 * 查询学生详情
	 */
	@Override
	public EnStudent selectEnStudentByStudentId(String studentId){
		return enStudentMapper.selectEnStudentByStudentId(studentId);
	}

	/**
	 * 查询学生列表
	 */
	@Override
	public PageList<EnStudent> selectEnStudentByList(JSONObject json){
		return enStudentMapper.selectEnStudentByList(json);
	}

	/**
	 * 分页查询学生列表
	 */
	@Override
	public PageList<EnStudent> selectEnStudentByPage(JSONObject json){
		return enStudentMapper.selectEnStudentByList(StrUtile.getPageJson(json));
	}

	/**
	 * 学生登录
	 */
	@Override
	public LoginUser studentLogin(EnStudent enStudent){
		if(StrUtile.isEmpty(enStudent.getStudentKey())){
			throw new SysException("请输入学号！");
		}
		if(StrUtile.isEmpty(enStudent.getStudentPassword())){
			throw new SysException("请输入密码！");
		}

		JSONObject json = new JSONObject();
		json.put("loginId", enStudent.getStudentKey());
		json.put("studentPassword", StrUtile.getMD5(enStudent.getStudentPassword()));
		List<EnStudent> userList = enStudentMapper.selectEnStudentByList(json).getList();
		if(ListUtile.isEmpty(userList)){
			throw new SysException("用户名密码错误！");
		}
		EnStudent student = userList.get(0);
		if(student.getIsDel() == 1){
			throw new SysException("账号已禁用，无法登录！");
		}

		if(!StrUtile.isEmpty(enStudent.getOpenId())){
			student.setOpenId(enStudent.getOpenId());
			enStudentMapper.updateEnStudent(student);
		}

		IUser user = new IUser();
		user.setUserId(student.getStudentId());
		user.setUserName(student.getStudentName());
		user.setTypes(enClasssTypeMapper.selectEnClasssUpTypeByList(student.getClasssId()));
		user.setClasssId(student.getClasssId());
		String token=StrUtile.getToken(user.getUserId(),StrUtile.getUUID());

		//将当前登录用户缓存到redis,设置token有效期为 108000 秒(30小时)
		SysRedis.setValue(TOKEN+":"+token, JSON.toJSON(user), 24*60*60);

		String key = user.getUserId()+DateUtile.toYmd();
		if(!SysRedis.hasKey(key)){
			// 记录
			SysRedis.setValue(key,token,24*60*60);
			int s = enRankingMapper.updateEnRankingDay(user.getUserId(),"1"); // 登录次数+1 学习天数+1
			if(s == 0){
				EnRanking enRanking = new EnRanking();
				enRanking.setStudentId(user.getUserId());
				enRanking.setLoginDay(1);
				enRanking.setLoginNum(1);
				enRanking.setClasssId(student.getClasssId());
				enRankingMapper.insertEnRanking(enRanking);
			}
		}else {
			enRankingMapper.updateEnRankingDay(user.getUserId(),null); // 登录次数+1
		}
		//记录日志
		return new LoginUser(token,user);
	}

	/**
	 * 修改用户openId
	 */
	@Override
	public void updateOpenId(String studentId){
		EnStudent student = enStudentMapper.selectEnStudentByStudentId(studentId);
		student.setOpenId(null);
		enStudentMapper.updateEnStudent(student);
	}

	/**
	 * 学生登录
	 */
	@Override
	public LoginUser wxLogin(String code){
		try {
			WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
			JSONObject json = new JSONObject();
			json.put("openId", session.getOpenid());
			List<EnStudent> userList = enStudentMapper.selectEnStudentByList(json).getList();
			if(ListUtile.isEmpty(userList)){
				return new LoginUser(session.getOpenid());
			}
			EnStudent student = userList.get(0);
			if(student.getIsDel() == 1){
				throw new SysException("账号已禁用，无法登录！");
			}

			IUser user = new IUser();
			user.setUserId(student.getStudentId());
			user.setUserName(student.getStudentName());
			user.setTypes(enClasssTypeMapper.selectEnClasssUpTypeByList(student.getClasssId()));
			user.setClasssId(student.getClasssId());
			String token=StrUtile.getToken(user.getUserId(),StrUtile.getUUID());

			//将当前登录用户缓存到redis,设置token有效期为 108000 秒(30小时)
			SysRedis.setValue(TOKEN+":"+token, JSON.toJSON(user), 24*60*60);

			String key = user.getUserId()+DateUtile.toYmd();
			if(!SysRedis.hasKey(key)){
				// 记录
				SysRedis.setValue(key,token,24*60*60);
				enRankingMapper.updateEnRankingDay(user.getUserId(),"1"); // 登录次数+1 学习天数+1
			}else {
				enRankingMapper.updateEnRankingDay(user.getUserId(),null); // 登录次数+1
			}

			//记录日志
			return new LoginUser(token,user);
		} catch (WxErrorException e) {
			throw new SysException("微信授权失败,请退出小程序重试！");
		}
	}

	/**
	 * 导入学生
	 */
	@Override
	public JSONObject importEnStudent(MultipartFile file) {
		JSONArray msgRute = new JSONArray();
		JSONArray sheetArray;
		//解析附件
		if(null == file){
			sheetArray = XlsUtil.getXlsJson(new File("C:\\Users\\Administrator\\Desktop\\许老师1班.xlsx"));
		}else {
			sheetArray = XlsUtil.getXlsJson(file);
		}
		if (sheetArray.isEmpty()) {
			throw new SysException("读取文件发生错误:表格为空");
		}
		List<EnClasss> list = enClasssMapper.selectEnClasssByList(new JSONObject()).getList();
		Map<String,String> classsNameMap = list.stream().collect(Collectors.toMap(EnClasss::getClasssName, EnClasss::getClasssId));

		List<EnStudent> deviceList = new ArrayList<>();
		// 获取第一个工作簿
		sheetArray = sheetArray.getJSONArray(0);
		int sess = 0;
		int error = 0;
		String userId = "20240912091243876590";
		for (int i = 2; i < sheetArray.size(); i++) {
			JSONArray rowArray = sheetArray.getJSONArray(i);
			JSONArray msg = new JSONArray();
			// 学号
			String studentKey = XlsUtil.getValue(rowArray, 0);

			// 学生姓名
			String studentName = XlsUtil.getValue(rowArray, 1);

			// 学生昵称
			String studentNickname = "";

			// 班级id
			String classsName = XlsUtil.getValue(rowArray, 2);
			if(StrUtile.isEmpty(studentKey)){
				msg.add(new XlsMsgBean("第" + (i + 1) + "行第A列", "学号为空!"));
			}else if(studentKey.length() < 6){
				msg.add(new XlsMsgBean("第" + (i + 1) + "行第A列", "学号长度至少为6!"));
			}
			if(StrUtile.isEmpty(studentName)){
				msg.add(new XlsMsgBean("第" + (i + 1) + "行第B列", "学生姓名为空!"));
			}
			if(StrUtile.isEmpty(studentNickname)){
				studentNickname = studentName;
			}
			if(StrUtile.isEmpty(classsName)){
				msg.add(new XlsMsgBean("第" + (i + 1) + "行第F列", "学生班级为空!"));
			}else if(!classsNameMap.containsKey(classsName)){
				msg.add(new XlsMsgBean("第" + (i + 1) + "行第F列", "班级名称错误或未创建!"));
			}

			// 学生登录密码
			EnStudent student = new EnStudent();
			student.setStudentKey(studentKey);
			student.setStudentName(studentName);
			student.setStudentNickname(studentNickname);
			student.setClasssId(classsNameMap.get(classsName));
			student.setStudentPassword(StrUtile.getMD5(studentKey.substring(studentKey.length() - 6)));

			// 4 更新db
			if (msg.isEmpty()) {
				student.setStudentId(StrUtile.getId());
				student.setCtime(new Date());
				student.setCreateUserId(userId);
				deviceList.add(student);
				sess++;
			} else {
				error++;
			}
			msgRute.addAll(msg);
		}
		if(!deviceList.isEmpty()){
			enStudentMapper.insertAllEnStudent(deviceList);
		}
		JSONObject rut = new JSONObject();
		rut.put("success", sess);
		rut.put("error", error);
		rut.put("list", msgRute);
		return rut;
	}

}